﻿using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Security.Principal;
using CloudStorageLight.Core;

namespace CloudStorageLight.Core.Tests
{
    /// <summary>
    /// CompositeBlobServiceTest の概要の説明
    /// </summary>
    [TestClass]
    public class CompositeBlobServiceTest
    {
        public CompositeBlobServiceTest()
        {
            //
            // TODO: コンストラクター ロジックをここに追加します
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///現在のテストの実行についての情報および機能を
        ///提供するテスト コンテキストを取得または設定します。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 追加のテスト属性
        //
        // テストを作成する際には、次の追加属性を使用できます:
        //
        // クラス内で最初のテストを実行する前に、ClassInitialize を使用してコードを実行してください
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext) 
        {
            using(var svc = CreateService())
            {
                if (svc.ExistsAsync("/Unit3/").Result) return;
                svc.CreateDirectoryAsync(CreateUser("admin", true), "/Unit3/", "admin").Wait();
                svc.CreateDirectoryAsync(CreateUser("admin", true), "/Unit3/Sub/", "admin").Wait();
                for (int idx = 0; idx < 100; idx++)
                {
                    var message = "テストデータ" + idx.ToString();
                    var contents = System.Text.UTF8Encoding.UTF8.GetBytes(message);
                    using (var st = new MemoryStream(contents))
                    {
                        svc.UploadFileAsync(CreateUser("Test1", true), "/Unit3/Sub/TEST" + idx.ToString() + ".txt", st).Wait();
                    }
                } 
                if (!svc.ExistsAsync("/Unit3/LOCALFILE/").Result) svc.CreateDirectoryAsync(CreateUser("admin", true), "/Unit3/LOCALFILE/", "admin").Wait();
                for (int idx = 0; idx < 100; idx++)
                {
                    var message = "テストデータ" + idx.ToString();
                    var contents = System.Text.UTF8Encoding.UTF8.GetBytes(message);
                    using (var st = new MemoryStream(contents))
                    {
                        svc.UploadFileAsync(CreateUser("Test2", true), "/Unit3/LOCALFILE/TEST" + idx.ToString() + ".txt", st).Wait();
                    }
                }
                if (!svc.ExistsAsync("/Unit3/SPS/Unit3/").Result) svc.CreateDirectoryAsync(CreateUser("admin", true), "/Unit3/SPS/Unit3/", "admin").Wait();
                for (int idx = 0; idx < 100; idx++)
                {
                    var message = "テストデータ" + idx.ToString();
                    var contents = System.Text.UTF8Encoding.UTF8.GetBytes(message);
                    using (var st = new MemoryStream(contents))
                    {
                        svc.UploadFileAsync(CreateUser("Test3", true), "/Unit3/SPS/Unit3/TEST" + idx.ToString() + ".txt", st).Wait();
                    }

                }

            }
        }
        //
        // クラス内のテストをすべて実行したら、ClassCleanup を使用してコードを実行してください
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 各テストを実行する前に、TestInitialize を使用してコードを実行してください
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 各テストを実行した後に、TestCleanup を使用してコードを実行してください
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        public static BlobUser CreateUser(string name, bool admin)
        {
            return new BlobUser(new GenericPrincipal(new GenericIdentity(name), null)) { IsAdmin=admin };
        }

        public class CompositeBlobService : BlobService
        {
            public CompositeBlobService()
                : base(new CloudAccount("compo3"), AppUtil.GetAppConfigValue("Composit.ConnectionString"))
            {

            }

            protected override BlobContainer Container
            {
                get
                {
                    if (_container == null)
                    {
                        var list = new List<BlobAdapterBase>();

                        var spsUrl = AppUtil.GetAppConfigValue("sps.url");
                        var user = AppUtil.GetAppConfigValue("sps.user");
                        var pass = AppUtil.GetAppConfigValue("sps.pass");
                        list.Add(new SpsBlobAdapter("/Unit3/SPS/", spsUrl, user, pass, "Shared Documents"));

                        var workFolder = "c:\\temp\\CompUnit";
                        if (!Directory.Exists(workFolder)) Directory.CreateDirectory(workFolder);
                        list.Add(new FileBlobAdapter("/Unit3/LOCALFILE/", workFolder + "\\"));


                        list.Add(new AzureBlobAdapter("/", "unit3", AppUtil.GetAppConfigValue("Composit.ConnectionString")));
                        _container = new CompositeBlobContainer("unittest",
                            AppUtil.GetAppConfigValue("Composit.ConnectionString"), list);
                    }

                    return _container;
                }
            }
            private BlobContainer _container;
        }

        private static BlobService CreateService()
        {
            return new CompositeBlobService();
        }


        [TestMethod]
        public void コンストラクタ()
        {
            Assert.IsNotNull(CreateService());
        }

        [TestMethod]
        public void さまざまな検索()
        {
            using (var svc = CreateService())
            {
                Assert.AreEqual(100, svc.ListFilesAsync(CreateUser("Test",  true), "/Unit3/Sub/").Result.OfType<BlobFile>().Count());
                Assert.AreEqual(100, svc.ListFilesAsync(CreateUser("Test",  true), "/Unit3/LOCALFILE/").Result.OfType<BlobFile>().Count());
                Assert.AreEqual(100, svc.ListFilesAsync(CreateUser("Test",  true), "/Unit3/SPS/Unit3/").Result.OfType<BlobFile>().Count());

            }
        }

        [TestMethod]
        public void SPSフォルダ作成_コピー_フォルダ削除()
        {
            using (var svc = CreateService())
            {
                if (!svc.ExistsAsync("/Unit3/SPS/Unit4/").Result)
                {
                    svc.CreateDirectoryAsync(CreateUser("Test", true), "/Unit3/SPS/Unit4/", null).Wait();
                }
                svc.MoveOrCopyFileAsync(CreateUser("Test", true), "/Unit3/Sub/TEST0.txt","/Unit3/SPS/Unit4/T1.txt", false).Wait();
                svc.MoveOrCopyFileAsync(CreateUser("Test", true), "/Unit3/Sub/TEST1.txt", "/Unit3/SPS/Unit4/Sub/T2.txt", false).Wait();
                using (var st = new MemoryStream())
                {
                    svc.DownloadFileAsync(CreateUser("Test", true), "/Unit3/SPS/Unit4/T1.txt", st).Wait();

                    var text = UTF8Encoding.UTF8.GetString(st.ToArray());
                    Assert.AreEqual("テストデータ0", text);

                }
                foreach (var file in svc.ListFilesAsync(CreateUser("Test", true), "/Unit3/SPS/Unit4/", 0, true).Result)
                {
                    if (file is BlobFile)
                    {
                        svc.DeleteFileAsync(CreateUser("Test", true), file.Path).Wait();
                    }
                }
                var list = svc.ListFilesAsync(CreateUser("Test", true), "/Unit3/SPS/Unit4/", 0, true).Result;
                list.Reverse();
                foreach (var file in list)
                {
                    if (file is BlobDirectory)
                    {
                        svc.DeleteDirectoryAsync(CreateUser("Test", true), file.Path).Wait();
                    }
                }
            }
        }

        [TestMethod]
        public void LocalFileフォルダ作成_コピー_フォルダ削除()
        {
            using (var svc = CreateService())
            {
                if (!svc.ExistsAsync("/Unit3/LOCALFILE/Unit4/").Result)
                {
                    svc.CreateDirectoryAsync(CreateUser("Test", true), "/Unit3/LOCALFILE/Unit4/", null).Wait();
                }
                svc.MoveOrCopyFileAsync(CreateUser("Test", true), "/Unit3/LOCALFILE/TEST0.txt", "/Unit3/LOCALFILE/Unit4/T1.txt", false).Wait();
                using (var st = new MemoryStream())
                {
                    svc.DownloadFileAsync(CreateUser("Test", true), "/Unit3/LOCALFILE/Unit4/T1.txt", st).Wait();

                    var text = UTF8Encoding.UTF8.GetString(st.ToArray());
                    Assert.AreEqual("テストデータ0", text);

                }
                foreach (var file in svc.ListFilesAsync(CreateUser("Test", true), "/Unit3/LOCALFILE/Unit4/", 0).Result)
                {
                    if (file is BlobFile)
                    {
                        svc.DeleteFileAsync(CreateUser("Test", true), file.Path).Wait();
                    }
                }
                foreach (var file in svc.ListFilesAsync(CreateUser("Test", true), "/Unit3/LOCALFILE/Unit4/", 0).Result)
                {
                    if (file is BlobDirectory)
                    {
                        svc.DeleteDirectoryAsync(CreateUser("Test", true), file.Path).Wait();
                    }
                }

            }
        }

        [TestMethod]
        public void Azureフォルダ作成_コピー_フォルダ削除()
        {
            using (var svc = CreateService())
            {
                if (!svc.ExistsAsync("/Unit3/Sub/Unit4/").Result)
                {
                    svc.CreateDirectoryAsync(CreateUser("Test", true), "/Unit3/Sub/Unit4/", null).Wait();
                }
                svc.MoveOrCopyFileAsync(CreateUser("Test", true), "/Unit3/Sub/TEST0.txt", "/Unit3/Sub/Unit4/T1.txt", false).Wait();
                using (var st = new MemoryStream())
                {
                    svc.DownloadFileAsync(CreateUser("Test", true), "/Unit3/Sub/Unit4/T1.txt", st).Wait();

                    var text = UTF8Encoding.UTF8.GetString(st.ToArray());
                    Assert.AreEqual("テストデータ0", text);

                }
                foreach (var file in svc.ListFilesAsync(CreateUser("Test", true), "/Unit3/Sub/Unit4/", 0).Result)
                {
                    if (file is BlobFile)
                    {
                        svc.DeleteFileAsync(CreateUser("Test", true), file.Path).Wait();
                    }
                }
                foreach (var file in svc.ListFilesAsync(CreateUser("Test", true), "/Unit3/Sub/Unit4/", 0).Result)
                {
                    if (file is BlobDirectory)
                    {
                        svc.DeleteDirectoryAsync(CreateUser("Test", true), file.Path).Wait();
                    }
                }

                svc.CreateDirectoryAsync(CreateUser("Test", true), "/Unit3/Sub/Unit4/", null).Wait();

            }
        }

    }
}
